package com.yami.shop.common.util;

import cn.hutool.core.util.ObjectUtil;
import com.google.common.base.Joiner;
import org.springframework.util.AntPathMatcher;

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 字符串工具类
 * @author vic_miao
 *
 */
public class StringUtils {
	public final static String SPLIT_PATTERN = ",";

    /**
     * 判断字符串是否为空
     *
     * @param str 需要判断的字符串
     * @return 如果为空则返回true，否则返回false
     */
    public static boolean isEmpty(String str) {
        int strLen;
        if (str == null || (strLen = str.length()) == 0) {
            return true;
        }
        if (Objects.equals("null", str)) {
            return true;
        }
        for (int i = 0; i < strLen; i++) {
            if ((Character.isWhitespace(str.charAt(i)) == false)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 判断字符串是否不空
     *
     * @param str 需要判断的字符串
     * @return 如果不为空则返回true，否则返回false
     */
    public static boolean isNotEmpty(String str) {
        return !isEmpty(str);
    }

    /**
     * 将list的每个字符串按照指定符号分隔
     *
     * @param list    需要分隔的list,注意list中的每个元素类型是字符串
     * @param pattern 指定分隔的符号，默认是英文逗号
     * @return 返回分隔后的字符串
     */
    public static String split(List<String> list, String pattern) {
        if (list == null || list.isEmpty() || list.size() < 1) {
            return "";
        }
        if (isEmpty(pattern)) {
            pattern = SPLIT_PATTERN;
        }
        return Joiner.on(pattern).join(list); // 以逗号分割
    }

    /**
     * 将set的每个字符串按照指定符号分隔
     * @param set
     * @param pattern
     * @return
     */
    public static String split(Set<String> set, String pattern) {
        if (set == null || set.isEmpty()) {
            return "";
        }
        if (isEmpty(pattern)) {
            pattern = SPLIT_PATTERN;
        }
        return Joiner.on(pattern).join(set); // 以逗号分割
    }

    /**
     * 以指定符号分隔字符串数组的每一个元素
     *
     * @param arr
     * @param pattern
     * @return
     */
    public static String split(String[] arr, String pattern) {
        if (arr == null || arr.length < 1) {
            return "";
        }
        if (isEmpty(pattern)) {
            pattern = SPLIT_PATTERN;
        }
        return Joiner.on(pattern).join(arr); // 以逗号分割
    }

    public static String strTo16(String s) {

        String str = "";
        for (int i = 0; i < s.length(); i++) {
            int ch = (int) s.charAt(i);
            String s4 = Integer.toHexString(ch);
            str = str + s4;
        }
        return str;
    }

    /**
     * 数组转成十六进制字符串
     *
     * @param b
     * @return HexString
     */
    public static String toHexString1(byte[] b) {
        StringBuffer buffer = new StringBuffer();
        for (int i = 0; i < b.length; ++i) {
            buffer.append(byteToHexString(b[i]));
        }
        return buffer.toString();
    }

    /**
     * byte转String
     * @param b
     * @return
     */
    private static String byteToHexString(byte b) {
        String s = Integer.toHexString(b & 0xFF);
        if (s.length() == 1) {
            return "0" + s;
        } else {
            return s;
        }
    }

    /**
     * byte[]转String
     * @param src
     * @return
     */
    public static String bytesToHexString(byte[] src){
        StringBuilder stringBuilder = new StringBuilder("");
        if (src == null || src.length <= 0) {
            return null;
        }
        for (int i = 0; i < src.length; i++) {
            int v = src[i] & 0xFF;
            String hv = Integer.toHexString(v);
            if (hv.length() < 2) {
                stringBuilder.append(0);
            }
            stringBuilder.append(hv);
        }
        return stringBuilder.toString();
    }

    public static byte[] hexStringToBytes(String hexString) {
        if (isEmpty(hexString)) {
            return null;
        }
        hexString = hexString.toUpperCase();
        int length = hexString.length() / 2;
        char[] hexChars = hexString.toCharArray();
        byte[] d = new byte[length];
        for (int i = 0; i < length; i++) {
            int pos = i * 2;
            d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
        }
        return d;
    }
    private static byte charToByte(char c) {
        return (byte) "0123456789ABCDEF".indexOf(c);
    }

    /**
     * 隐藏字符串的中间N位
     * @param str
     * @param start  开始位(包含)
     * @param end   结束位（不包含）
     * @param character  需要替换的字符，默认是*
     * @return
     */
    public static String hiddenStr(String str,int start,int end,String character){
        if(isEmpty(character)){
            character = "*";
        }
        String idCode = "";
        for (int i=0 ; i<str.length(); i++) {
            if(i >= start && i < end){
                idCode +=  character;
            }else{
                idCode += str.charAt(i);
            }
        }
        return idCode;
    }
	/**
	 * uuid
	 *
	 * @return
	 */
	public static String getUUID() {
		return UUID.randomUUID().toString().replace("-", "").toUpperCase();
	}

    /**
     * 获取指定url中的某个参数
     * @param url
     * @param name
     * @return
     */
    public static String getParamByUrl(String url, String name) {
        url += "&";
        String pattern = "(\\?|&){1}#{0,1}" + name + "=[a-zA-Z0-9]*(&{1})";
        Pattern r = Pattern.compile(pattern);
        Matcher m = r.matcher(url);
        if (m.find( )) {
            return m.group(0).split("=")[1].replace("&", "");
        } else {
            return null;
        }
    }
    /**
     * 判断评论是否为垃圾评论（仅通过单一字符重复出现来判断，以后可以扩展更多的检测方法）
     *
     * @param content
     * @return
     */
    public static Boolean isCommentSpam(String content) {
        if (content == null) {
            return true;
        }
        char[] chars = content.toCharArray();
        // 最大重复次数
        Integer maxCount = 4;
        for (int a = 0; a < chars.length; a++) {
            Integer count = 1;
            for (int b = a; b < chars.length - 1; b++) {
                if (chars[b + 1] == chars[b]) {
                    count++;
                    // 判断字符重复的次数是否大于阈值
                    if (count >= maxCount) {
                        return true;
                    }
                    continue;
                } else {
                    break;
                }
            }
        }
        return false;
    }
    public static Map<String,Object> obj2Map(Object obj) throws Exception{
        Map<String,Object> map=new HashMap<String, Object>();
        BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
        for (PropertyDescriptor property : propertyDescriptors) {
            String key = property.getName();
            if (key.compareToIgnoreCase("class") == 0) {
                continue;
            }
            Method getter = property.getReadMethod();
            Object value = getter!=null ? getter.invoke(obj) : null;
            map.put(key, value);
        }
        return map;
    }
    public static Map<String,Object> obj2MapNotNull(Object obj) throws Exception{
        Map<String,Object> map=new HashMap<String, Object>();
        BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
        for (PropertyDescriptor property : propertyDescriptors) {
            String key = property.getName();
            if (key.compareToIgnoreCase("class") == 0) {
                continue;
            }
            Method getter = property.getReadMethod();
            Object value = getter!=null ? getter.invoke(obj) : null;
            if(ObjectUtil.isNotNull(value)){
                map.put(key, value);
            }
        }
        return map;
    }
    public static Map<String,String> obj2StringMapNotNull(Object obj) throws Exception{
        Map<String,String> map=new HashMap<String, String>();
        BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
        for (PropertyDescriptor property : propertyDescriptors) {
            String key = property.getName();
            if (key.compareToIgnoreCase("class") == 0) {
                continue;
            }
            Method getter = property.getReadMethod();
            Object value = getter!=null ? getter.invoke(obj) : null;
            if(ObjectUtil.isNotNull(value)){
                map.put(key, value.toString());
            }
        }
        return map;
    }
    public static Object map2Obj(Map<String,Object> map,Class<?> clz) throws Exception{
        if (map == null)
            return null;
        Object obj = clz.newInstance();
        BeanInfo beanInfo = Introspector.getBeanInfo(obj.getClass());
        PropertyDescriptor[] propertyDescriptors = beanInfo.getPropertyDescriptors();
        for (PropertyDescriptor property : propertyDescriptors) {
            Method setter = property.getWriteMethod();
            if (setter != null) {
                setter.invoke(obj, map.get(property.getName()));
            }
        }
        return obj;
    }

    /**
     * 查找指定字符串是否匹配指定字符串列表中的任意一个字符串
     *
     * @param str 指定字符串
     * @param strs 需要检查的字符串数组
     * @return 是否匹配
     */
    public static boolean matches(String str, List<String> strs) {
        if (ObjectUtil.isEmpty(str) || ObjectUtil.isEmpty(strs))
        {
            return false;
        }
        for (String pattern : strs)
        {
            if (isMatch(pattern, str))
            {
                return true;
            }
        }
        return false;
    }
    /**
     * 判断url是否与规则配置:
     * ? 表示单个字符;
     * * 表示一层路径内的任意字符串，不可跨层级;
     * ** 表示任意层路径;
     *
     * @param pattern 匹配规则
     * @param url 需要匹配的url
     * @return
     */
    private static boolean isMatch(String pattern, String url)
    {
        AntPathMatcher matcher = new AntPathMatcher();
        return matcher.match(pattern, url);
    }
}
